package com.hui.platform.falseworkapi.service.base.oss.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.*;
import com.hui.platform.falseworkapi.service.base.oss.constant.AliyunOssProperties;
import com.hui.platform.falseworkapi.service.base.oss.constant.OssDirEnum;
import com.hui.platform.falseworkapi.service.base.oss.dto.*;
import com.hui.platform.falseworkapi.service.base.oss.service.OssService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.util.Date;
import java.util.Optional;
import java.util.UUID;

/**
 *  OSS上传管理Service实现类
 * @author hui
 *
 */
@Service
@Slf4j
public class OssServiceImpl implements OssService {

	@Autowired
	private AliyunOssProperties aliyunOssProperties;

	@Autowired
	private OSS ossClient;
	
	/**
	 * 	直传回调-----------
	 */
	
	/**
	 * 签名生成
	 */
	@Override
	public OssPolicyResult policy() {
		OssPolicyResult result = new OssPolicyResult();
		// 签名有效期
		Date expiration = new Date((System.currentTimeMillis() + aliyunOssProperties.getPolicyExpire() * 1000));
		// 文件大小
		long maxSize = aliyunOssProperties.getMaxSize() * 1024 * 1024;
		//请求地址
		String action = getActionUrl();
		// 回调
		OssCallbackParam callback = new OssCallbackParam()
										.setCallbackUrl(aliyunOssProperties.getCallback())
										.setCallbackBody("filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}")
										.setCallbackBodyType("application/x-www-form-urlencoded");
		try {
			//签名条件
			PolicyConditions policyConds = new PolicyConditions();
			//文件大小范围
			policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, maxSize);
			//文件开始目录
			policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, OssDirEnum.FILE_DIR.getDir());
			String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
			byte[] binaryData = postPolicy.getBytes("utf-8");
			String policy = BinaryUtil.toBase64String(binaryData);
			String signature = ossClient.calculatePostSignature(postPolicy);
			//回调结结果
			String callbackData = BinaryUtil.toBase64String(JSON.toJSONString(callback, SerializerFeature.WriteMapNullValue).getBytes("utf-8"));
			//设置结果属性
			result.setAccessKeyId(aliyunOssProperties.getAccessKeyId())
					.setPolicy(policy)
					.setSignature(signature)
					.setDir(OssDirEnum.FILE_DIR.getDir())
					.setHost(action)
					//返回回调地址，前端需要--暂时不用
					.setCallback(callbackData);
		} catch (Exception e) {
			log.error("签名生成失败", e);
			throw new RuntimeException("签名生成失败"+e.getMessage());
		}
		return result;
	}

	/**
	 * 	回调结果
	 */
	@Override
	public OssCallbackResult callback(HttpServletRequest request) {
		OssCallbackResult result= new OssCallbackResult();
		String filename = request.getParameter("filename");
		filename = getActionUrl().concat("/").concat(Optional.ofNullable(filename).orElseThrow(()->new RuntimeException("文件名为空")));
		result.setFilename(filename)
				.setSize(request.getParameter("size"))
				.setMimeType(request.getParameter("mimeType"))
				.setWidth(request.getParameter("width"))
				.setHeight(request.getParameter("height"));
		return result;
	}

	/**
	 * 文件上传
	 */
	@Override
	public String uploadFile(String fileName, InputStream in, OssDirEnum dirType){
		//截取后缀名
		String extName = fileName.substring(fileName.lastIndexOf("."));
		//相关参数
		String bucketName = aliyunOssProperties.getBucketName();
        //文件总名称key,dirType.getDir():指定保存目录，没有则新建
		String key = dirType.getDir()+UUID.randomUUID().toString().replace("-", "") + (extName.equals(".") ? "" : extName);
		log.info("the key:"+key);
        //容器不存在，就创建
        if(!ossClient.doesBucketExist(bucketName)){
            ossClient.createBucket(bucketName);
            CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
            createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
            ossClient.createBucket(createBucketRequest);
        }
		//构建上传请求
		PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName,key,in); 
		//上传
		ossClient.putObject(putObjectRequest);
		//返回访问链接
		String filename = getActionUrl().concat("/").concat(key);
		return filename;
	}

	/**
	 * 删除文件
	 */
	@Override
	public boolean deleteFile(String url) {
		ossClient.deleteObject(aliyunOssProperties.getBucketName(), getKeyByUrl(url));
		return true;
	}
	
	/**
	 * 获取文件信息
	 */
	@Override
	public FileInfo getFileInfo(String url) {
		ObjectMetadata omdata = ossClient.getObjectMetadata(aliyunOssProperties.getBucketName(), getKeyByUrl(url));
		FileInfo fileInfo = new FileInfo();
		fileInfo.setContentType(omdata.getContentType());
		fileInfo.setFilename(url);
		fileInfo.setFileSize(omdata.getContentLength());
		return fileInfo;
	}

	/**
	 * 截取url获得key
	 * @param url
	 * @return
	 */
	private String getKeyByUrl(String url) {
		Assert.hasLength(url, "url is empty!");
		url=url.trim();
		String prefix=getActionUrl().concat("/");
		return url.startsWith(prefix)?url.replaceFirst(prefix, ""):url;	
	}

	/**
	 * 获取访问连接
	 * @return
	 */
	private String getActionUrl() {
		return "https://" + aliyunOssProperties.getBucketName() + "." + aliyunOssProperties.getEndpoint();
	}
}
